#include "CaptureSound.h"

using namespace ipsound;

CaptureSound::CaptureSound( MutexBuffer* buffer )
:buffer( buffer )
,soundBuf8( 0 )
,soundBufOffset( 0 )
,channelsNum( 1 )
,bitsPerSample( 16 )
,samplesPerSec( 8000 )
{
	LPDIRECTSOUNDCAPTURE8 capture = 0;
	DirectSoundCaptureCreate8( 0, &capture, 0 );
	InitWaveFormat();

	memset(&SoundBufDesc,0,sizeof(DSCBUFFERDESC));
	SoundBufDesc.dwSize = sizeof(DSCBUFFERDESC);
	SoundBufDesc.dwFlags = SoundBufDesc.dwReserved = SoundBufDesc.dwFXCount = 0;
	SoundBufDesc.dwBufferBytes = wfx.nAvgBytesPerSec * 2;
	SoundBufDesc.lpwfxFormat = &wfx;
	SoundBufDesc.lpDSCFXDesc = 0;

	LPDIRECTSOUNDCAPTUREBUFFER soundBuf = 0;
	capture->CreateCaptureBuffer( &SoundBufDesc, &soundBuf, 0 );
	soundBuf->QueryInterface(IID_IDirectSoundCaptureBuffer8, (void**)&soundBuf8);
	soundBuf->Release();
}

void* CaptureSound::Thread()
{
	LPDIRECTSOUNDNOTIFY8 notify;
	HANDLE bufEvent = CreateEvent( 0, true, false, 0);
	DSBPOSITIONNOTIFY  notifyPos[2];

	soundBuf8->QueryInterface(IID_IDirectSoundNotify, (LPVOID*)&notify);

	notifyPos[0].dwOffset = wfx.nAvgBytesPerSec - 1;
	notifyPos[0].hEventNotify = bufEvent;

	notifyPos[1].dwOffset = wfx.nAvgBytesPerSec * 2 - 1;
	notifyPos[1].hEventNotify = bufEvent;

	notify->SetNotificationPositions( 2, notifyPos );
	notify->Release();

	soundBuf8->Start( DSCBSTART_LOOPING );
	ThreadStarted();

	while( true )
	{
		
		HRESULT result = WaitForSingleObject( bufEvent, INFINITE );

		GetDataFromSoundBuffer();
		
		ResetEvent( bufEvent );
	}

	CloseHandle( bufEvent );

	return 0;
}

CaptureSound::~CaptureSound()
{
	soundBuf8->Release();
}

void CaptureSound::InitWaveFormat()
{
	memset( &wfx, 0, sizeof(WAVEFORMATEX) );
	wfx.wFormatTag = WAVE_FORMAT_PCM;
	wfx.nChannels = channelsNum;
	wfx.nSamplesPerSec = samplesPerSec;
	wfx.wBitsPerSample = bitsPerSample;
	wfx.nBlockAlign = (wfx.wBitsPerSample * wfx.nChannels) / 8;
	wfx.nAvgBytesPerSec = samplesPerSec * wfx.nBlockAlign;
}

void CaptureSound::GetDataFromSoundBuffer()
{
	void* captureData = 0;
	unsigned long captureLength = 0;
	void* captureData2 = 0;
	unsigned long captureLength2 = 0;
	void* playData = NULL;
	unsigned int  dataWrote = 0;
	unsigned long readPos = 0;

	soundBuf8->GetCurrentPosition( 0, &readPos);

	long lockSize = readPos - soundBufOffset;
	if( lockSize < 0 )
	  lockSize += SoundBufDesc.dwBufferBytes;

	soundBuf8->Lock( soundBufOffset, lockSize, &captureData, &captureLength, &captureData2, &captureLength2, 0L );
	buffer->Write( captureData, captureLength );

	if ( captureData2 )
		buffer->Write( captureData2, captureLength2 );

	soundBuf8->Unlock(captureData, captureLength, captureData2, captureLength2);

	soundBufOffset += captureLength; 
	soundBufOffset %= SoundBufDesc.dwBufferBytes; 
	soundBufOffset += captureLength2; 
	soundBufOffset %= SoundBufDesc.dwBufferBytes;
}


